import { getDomain } from "../request.js";
import { uploadInit, handlerBtn, clearFiles, setHeaders } from "./layui-upload-common.js";
import { sheet } from "./layui-upload-sheet.js";

export let uploadFilesApi = {
    // 上传组件
    upload: {},

    // 选择的文件列表
    files: {},

    // 数量
    number: {},

    /**
     * dom 元素模板
     *
     * @returns {string|{image(*): string}}
     */
    template() {
        return {
            /**
             * 获取 html 模板
             *
             * @param resource
             * @returns {string}
             */
            image(resource) {
                let html = `<div class="upload__item" data-index="${resource.index}">
                                <!-- 资源模块 -->
                                <div class="upload__img">
                                    <img src="${resource.image}">
                                </div>

                                <!-- 操作按钮 -->
                                <div class="upload__resource__action_btn upload__resource__action_btn--left"><i class="layui-icon">&#xe603;</i></div>
                                <div class="upload__resource__action_btn upload__resource__action_btn--right"><i class="layui-icon">&#xe602;</i></div>
                                <div class="upload__resource__action_btn upload__resource__action_btn--close"><i class="layui-icon">&#x1006;</i></div>

                                <!-- 上传状态 -->
                                <div class="upload__resource__notify ${resource.input ? '' : 'upload__resource__notify--none'}"><span>${resource.input ? '上传成功' : ''}</span></div>
                                
                                <!-- input -->
                                <input type="hidden" name="${resource.field}[]" value="${resource.input ? resource.input : ''}">
                            </div>`;

                return html;
            },

            /**
             * 获取 html 模板
             *
             * @param resource
             * @returns {string}
             */
            video(resource) {
                let html = `<div class="upload__item" data-index="${resource.index}">
                                <!-- 资源模块 -->
                                <div class="upload__video">
                                    <video controls src="${resource.video}"></video>
                                </div>

                                <!-- 操作按钮 -->
                                <div class="upload__resource__action_btn upload__resource__action_btn--left"><i class="layui-icon">&#xe603;</i></div>
                                <div class="upload__resource__action_btn upload__resource__action_btn--right"><i class="layui-icon">&#xe602;</i></div>
                                <div class="upload__resource__action_btn upload__resource__action_btn--close"><i class="layui-icon">&#x1006;</i></div>

                                <!-- 上传状态 -->
                                <div class="upload__resource__notify ${resource.input ? '' : 'upload__resource__notify--none'}"><span>${resource.input ? '上传成功' : ''}</span></div>
                                
                                <!-- input -->
                                <input type="hidden" name="${resource.field}[]" value="${resource.input ? resource.input : ''}">
                            </div>`;

                return html;
            },

            /**
             * 获取 html 模板
             *
             * @param resource
             * @returns {string}
             */
            file(resource) {
                let html = `<div class="upload__item" data-index="${resource.index}">
                                <!-- 资源模块 -->
                                <div class="upload__file">
                                    <span>${resource.file}</span>
                                </div>

                                <!-- 操作按钮 -->
                                <div class="upload__resource__action_btn upload__resource__action_btn--left"><i class="layui-icon">&#xe603;</i></div>
                                <div class="upload__resource__action_btn upload__resource__action_btn--right"><i class="layui-icon">&#xe602;</i></div>
                                <div class="upload__resource__action_btn upload__resource__action_btn--close"><i class="layui-icon">&#x1006;</i></div>

                                <!-- 上传状态 -->
                                <div class="upload__resource__notify ${resource.input ? '' : 'upload__resource__notify--none'}"><span>${resource.input ? '上传成功' : ''}</span></div>
                                
                                <!-- input -->
                                <input type="hidden" name="${resource.field}[]" value="${resource.input ? resource.input : ''}">
                            </div>`;

                return html;
            }
        }
    },

    /***
     * 获取当前上传资源容器，并重置所有 input 名称
     *
     * @param config
     * @param index
     * @returns {*}
     */
    handlerUploadItemDom(config, index = false) {
        let dom;

        $(config.resetAction).next('.rain-resource__resource-box').find('.upload__item').each((i, item) => {
            // 重置input名称
            $(item).children('input').attr('name', `${config.field}[]`);

            // 获取当前 资源容器
            if (index && $(item).data('index') == index) dom = $(item);
        });

        return dom;
    },

    /**
     * 获取回调方法操作
     *
     * @param config
     * @returns {{uploadBox: jQuery, resetResource(): void, done(*, *): void}}
     */
    getCallback(config) {
        return {
            uploadBox: $(config.resetAction).next('.rain-resource__resource-box').children('.layui-upload-list'),

            /**
             * 重置资源
             */
            resetResource() {
                this.uploadBox.html('');
            },

            /**
             * 自定义回调
             *
             * @param res
             * @param uploadItemDom
             */
            done(res, uploadItemDom) {
                let input;

                if (200 == res.code) {
                    input = res.data.input;

                    uploadItemDom.children('.upload__resource__notify').removeClass('upload__resource__notify--none');
                } else {
                    uploadItemDom.children('.upload__resource__notify').removeClass('upload__resource__notify--none');
                    uploadItemDom.children('.upload__resource__notify').addClass('upload__resource__notify--fail');
                }

                uploadItemDom.children('input').val(input);
                uploadItemDom.children('.upload__resource__notify').children('span').text(res.msg);
            }
        }
    },

    /**
     * 图片上传
     *
     * @param config
     * @param initConfig
     */
    image(config, initConfig) {
        // 自定义配置
        let customize = {

            // 组件配置
            config: {
                field: 'img',
                size: 2048,
                accept: 'images',
                acceptMime: 'image/png,image/jpg,image/jpeg',

                ...config
            },

            // 个性化配置
            customize: {
                // 自定义回调
                ...this.getCallback(config),

                /**
                 * 初始化
                 */
                init() {
                    if (typeof initConfig.resource == 'undefined' || typeof initConfig.resource.list == 'undefined') return;

                    // 初始化资源数据
                    initConfig.resource.list.forEach(item => {
                        this.uploadBox.append(uploadFilesApi.template().image({
                            image: item.url,
                            index: '',
                            field: initConfig.field,
                            input: item.input,
                        }));
                    });
                },

                /**
                 * 选择文件触发回调
                 *
                 * @param index
                 * @param file
                 * @param result
                 */
                choose(index, file, result) {
                    this.uploadBox.append(uploadFilesApi.template().image({
                        image: result,
                        index,
                        field: initConfig.field
                    }));
                }
            }

        };

        this.render(customize, initConfig, 'upload-file-img');
    },

    /**
     * 视频上传
     *
     * @param config
     * @param initConfig
     */
    video(config, initConfig) {
        // 自定义配置
        let customize = {

            // 组件配置
            config: {
                field: 'video',
                size: 20480,
                accept: 'video',
                acceptMime: 'video/mp4,video/webm,video/ogg',

                ...config
            },

            // 个性化配置
            customize: {
                // 自定义回调
                ...this.getCallback(config),

                /**
                 * 初始化
                 */
                init() {
                    if (typeof initConfig.resource == 'undefined' || typeof initConfig.resource.list == 'undefined') return;

                    // 初始化资源数据
                    initConfig.resource.list.forEach(item => {
                        this.uploadBox.append(uploadFilesApi.template().video({
                            video: item.url,
                            index: '',
                            field: initConfig.field,
                            input: item.input,
                        }));
                    });
                },

                /**
                 * 选择文件触发回调
                 *
                 * @param index
                 * @param file
                 * @param result
                 */
                choose(index, file, result) {
                    this.uploadBox.append(uploadFilesApi.template().video({
                        video: result,
                        index,
                        field: initConfig.field,
                    }));
                }
            }

        };

        this.render(customize, initConfig, 'upload-file-video');
    },

    /**
     * 文件上传
     *
     * @param config
     * @param initConfig
     */
    file(config, initConfig) {
        // 自定义配置
        let customize = {

            // 组件配置
            config: {
                field: 'file',
                size: 20480,
                accept: 'file',
                acceptMime: 'video/*,image/*',

                ...config
            },

            // 个性化配置
            customize: {
                // 自定义回调
                ...this.getCallback(config),

                /**
                 * 初始化
                 */
                init() {
                    if (typeof initConfig.resource == 'undefined' || typeof initConfig.resource.list == 'undefined') return;


                    // 初始化资源数据
                    initConfig.resource.list.forEach(item => {
                        let fileName = item.url.substr(item.url.lastIndexOf('/') + 1);

                        this.uploadBox.append(uploadFilesApi.template().file({
                            file: fileName,
                            index: '',
                            field: initConfig.field,
                            input: item.input,
                        }));
                    });
                },

                /**
                 * 选择文件触发回调
                 *
                 * @param index
                 * @param file
                 * @param result
                 */
                choose(index, file, result) {
                    this.uploadBox.append(uploadFilesApi.template().file({
                        file: file.name,
                        index,
                        field: initConfig.field,
                    }));
                }
            }

        };

        this.render(customize, initConfig, 'upload-file-file');
    },

    /**
     * 渲染上传
     *
     * @param config
     * @param initConfig
     * @param url
     */
    render: (config, initConfig, url) => {
        // 渲染
        uploadFilesApi.upload.render({
            url: getDomain() + url,
            auto: false,
            multiple: true,
            number: 0,

            // 额外属性
            customize: {
                // 选择的文件
                files: {},

                // 加载状态
                load: false,
            },

            // 重置按钮
            resetAction: '',

            /**
             * 选择文件回调
             *
             * @param obj
             */
            choose(obj) {
                // 文件下标
                let indexList = Object.keys(this.customize.files);

                // 添加文件
                uploadFilesApi.files[this.elem.attr('id')] = this.customize.files = obj.pushFile();

                // 清空file下的value，避免不可重复上传资源
                $(this.elem).next().val('');

                // 预览资源
                for (let i in this.customize.files) {
                    if (indexList.includes(i)) continue;

                    // 按钮显示并处理
                    handlerBtn(this, true);

                    // 触发自定义回调
                    config.customize.choose(i, this.customize.files[i], URL.createObjectURL(this.customize.files[i]));
                }

                // 是否分片上传
                if (typeof config.config.sheet !== 'undefined' && config.config.sheet) sheet(config, this);

                // 重置按钮
                if (typeof $._data($(this.resetAction)[0], 'events') != 'undefined') $(this.resetAction).unbind();

                // 重置点击清空资源
                $(this.resetAction).one('click', () => {
                    // 隐藏按钮 和 更改文字
                    handlerBtn(this, false);

                    // 隐藏当前资源模块
                    config.customize.resetResource();

                    // 清空file下的value，避免不可重复上传资源
                    $(this.elem).next().val('');

                    // 清除File
                    clearFiles(this.customize.files);
                });

            },

            /**
             * 上传文件前回调
             */
            before() {
                // 设置header头
                this.headers = setHeaders();

                if (Object.keys(this.customize.files).length != 0) this.customize.load = layer.load(2);
            },

            /**
             * 正常回调
             *
             * @param res
             * @param index
             * @returns {Promise<void>}
             */
            done: async function (res, index) {
                // 关闭 加载层
                this.closeLoad(index, this.elem.attr('id'));

                // 触发回调处理
                this.handlerCustomizeCallback(res, index);

                // 验证回调
                if (res.code == 200) {
                    // 隐藏开始上传按钮
                    this.bindAction.hide();

                    // 上传成功则删除文件对象
                    delete this.customize.files[index];
                } else {
                    this.bindAction.text('重新上传');
                }
            },

            /**
             * 错误回调
             *
             * @param index
             * @param upload
             */
            error(index, upload) {
                // 关闭 加载层
                this.closeLoad(index, this.elem.attr('id'));

                // 重新上传
                this.bindAction.text('重新上传');

                // 触发回调处理
                this.handlerCustomizeCallback({
                    code: 500,
                    msg: '网络较差，重新尝试',
                }, index);
            },

            /**
             * 触发上传完成自定义回调
             *
             * @param res
             * @param index
             */
            handlerCustomizeCallback(res, index) {
                // 重置input 名称，并获取当前index所在容器元素
                let uploadItemBox = uploadFilesApi.handlerUploadItemDom({
                    resetAction: this.resetAction,
                    field: initConfig.field
                }, index);

                // 触发自定义函数
                config.customize.done(res, uploadItemBox);
            },

            /**
             * 加载所有文件，关闭加载框
             *
             * @param index
             * @param elem
             */
            closeLoad(index, elem) {
                if (typeof uploadFilesApi.number[elem] === 'undefined' || uploadFilesApi.number[elem] === 0) uploadFilesApi.number[elem] = Object.keys(uploadFilesApi.files[elem]).length;

                uploadFilesApi.number[elem] = uploadFilesApi.number[elem] - 1 <= 0 ? 0 : uploadFilesApi.number[elem] - 1;
                if (uploadFilesApi.number[elem] === 0) {
                    layer.close(this.customize.load);

                    // 触发上传完成
                    dialog('全部上传完成');
                }
            },

            // 自定义配置项
            ...config.config
        });

        /**
         * 初始化操作
         */
        (function () {
            // 移动位置事件
            let dom = $(config.config.resetAction).next('.rain-resource__resource-box').children('.layui-upload-list');
            uploadFilesApi.left(dom);
            uploadFilesApi.right(dom);
            uploadFilesApi.close(dom);

            // 初始化操作
            uploadInit(config, initConfig);
        }());
    },

    /**
     * 向左移动
     *
     * @param dom
     */
    left(dom) {
        dom.on('click', '.upload__resource__action_btn--left', function () {
            let box = $(this).parents('.upload__item');

            box.insertBefore(box.prev());
        });
    },

    /**
     * 向右移动
     *
     * @param dom
     */
    right(dom) {
        dom.on('click', '.upload__resource__action_btn--right', function () {
            let box = $(this).parents('.upload__item');

            box.insertAfter(box.next());
        });
    },

    /**
     * 关闭
     *
     * @param dom
     */
    close(dom) {
        dom.on('click', '.upload__resource__action_btn--close', function () {
            let elem = $(this).parents('.rain-resource').children('.layui-upload-file').prev().attr('id');

            // 删除元素
            let index = $(this).parents('.upload__item').data('index');
            $(this).parents('.upload__item').remove();

            // 删除上传文件
            if (uploadFilesApi.files[elem] !== undefined && uploadFilesApi.files[elem][index] !== undefined) delete uploadFilesApi.files[elem][index];

            if (typeof uploadFilesApi.number[elem] !== 'undefined') uploadFilesApi.number[elem]--;
        });
    }
};
